{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Simulating noisy quantum circuits with Paddle Quantum\n",
    "\n",
    "<em> Copyright (c) 2021 Institute for Quantum Computing, Baidu Inc. All Rights Reserved. </em>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Introduction to quantum noises\n",
    "\n",
    "In ideal models, we usually assume that quantum circuits are operating on a **closed physical system**. However, real quantum devices suffer from **incoherent noises** introduced by unwanted interactions between the system and the environment. This type of noise can significantly change the performance of quantum computation tasks and hence can hardly be ignored for near-term quantum devices. Consequently, designing robust quantum algorithms under the presence of noise is crucial for utilizing quantum computation in the real world. With the noise module of Paddle Quantum, we can now not only design and simulate quantum algorithms but also examine various noises' influence and further develop error mitigation schemes.\n",
    "\n",
    "## Building noise models in Paddle Quantum\n",
    "\n",
    "### Noise model and quantum channel\n",
    " \n",
    "The evolution of a closed quantum system is always unitary. Mathematically, we can describe such a process as implementing a parameterized quantum circuit $U(\\vec{\\theta})$,\n",
    "\n",
    "$$\n",
    "\\rho \\longrightarrow U(\\vec{\\theta}) \\rho U^\\dagger(\\vec{\\theta}),\n",
    "\\tag{1}\n",
    "$$\n",
    "\n",
    "where $\\rho$ is the initial quantum state, $\\vec{\\theta}$ is a vector containing all the parameters. The most intuitive type of noise one can think of is the error that appears in these parameters, \n",
    "$$\n",
    "\\rho \\longrightarrow U(\\vec{\\theta}+\\vec{\\epsilon}) \\rho U^\\dagger(\\vec{\\theta}+\\vec{\\epsilon}),\n",
    "\\tag{2}\n",
    "$$\n",
    "\n",
    "$\\vec{\\epsilon}$ can be a white noise sampled from Gaussian distributions. This kind of noise is a specific example of **coherent noises**. Coherent noise usually occurs due to device calibration errors or quantum control errors. We want to emphasize that one also uses unitary transformation $U(\\vec{\\epsilon})$ to describe coherent noises. In certain cases, coherent noises can be more damaging than incoherent noises [1].  \n",
    "\n",
    "Most of the time, the real problem lies on the evolution of an **open quantum system** that is non-unitary. Under this circumstance, we need a more general description beyond the unitary transformation to characterize incoherent noises, the language of **quantum channels**. To keep the discussion precise, we use *operator-sum representation* [2] to introduce a quantum channel as \n",
    "\n",
    "$$\n",
    "\\mathcal{E}(\\rho) =  \\sum_{k=0}^{m-1} E_k \\rho E_k^{\\dagger},\n",
    "\\tag{3}\n",
    "$$\n",
    "\n",
    "where $\\{E_k\\}$ are *Kraus* operators, and they satisfy the completeness condition  $\\sum_k E_k^\\dagger E_k = I$. Mathematically, a quantum channel is completely positive and trace-preserving [2].\n",
    "\n",
    "Under this representation, we can explicitly observe the results of implementing a quantum channel: Suppose we start with a pure state $\\rho = |\\psi\\rangle\\langle \\psi|$, then we send it through a noisy quantum channel (e.g., $m = 2$ ). Eventually, we will get a mixed state $\\mathcal{E}(\\rho) = E_0 \\rho E_0^\\dagger + E_1 \\rho E_1^\\dagger$. Let's take the bit flip noise as an example: \n",
    "\n",
    "$$\n",
    "\\mathcal{E}_{BF}(\\rho) = (1 - p) I \\rho I+ p X \\rho X,\n",
    "\\tag{4}\n",
    "$$\n",
    "\n",
    "where $X,I$ are Pauli operators. The corresponding *Kraus* operators are:\n",
    "\n",
    "$$\n",
    "E_0 = \\sqrt{1-p}\n",
    "\\begin{bmatrix}\n",
    "1&0 \\\\\n",
    "0&1\n",
    "\\end{bmatrix},\n",
    "E_1 = \\sqrt{p}\n",
    "\\begin{bmatrix}\n",
    "0& 1 \\\\\n",
    "1 &0\n",
    "\\end{bmatrix}.\n",
    "\\tag{5}\n",
    "$$\n",
    "\n",
    "The physical meaning of this quantum channel is there exist a  probability $p$ that the state $|0\\rangle$ will flip into $|1\\rangle$, and vice versa. In Paddle Quantum, we can use this quantum channel by `Circuit.bit_flip(p, which_qubit)`, where `p` is the noise level.\n",
    "\n",
    "**Note:** For a quantum channel, the Kraus operator representation is not necessarily unique [3]."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Implementation with Paddle Quantum\n",
    "\n",
    "In this section, we will learn how to build a noise model in Paddle Quantum. First, we initialize a qubit to $|0\\rangle$. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2021-04-09T02:32:24.919291Z",
     "start_time": "2021-04-09T02:32:22.237264Z"
    }
   },
   "outputs": [
    {
     "data": {
      "image/png": "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",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    },
    {
     "data": {
      "text/plain": [
       "{'0': 1.0, '1': 0.0}"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import paddle_quantum\n",
    "from paddle_quantum.ansatz import Circuit\n",
    "\n",
    "# Change to density matrix mode\n",
    "paddle_quantum.set_backend('density_matrix')\n",
    "\n",
    "# Define the number of qubits, here we use one single qubit\n",
    "num_qubits = 1\n",
    "\n",
    "# Initialize the quantum circuit\n",
    "cir = Circuit(num_qubits)\n",
    "\n",
    "# Initialize the qubit to |0><0| \n",
    "init_state = paddle_quantum.state.zero_state(num_qubits)\n",
    "\n",
    "# Mesure in the computational basis \n",
    "cir(init_state).measure(shots = 1024, plot = True)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Then, we add a bit flip channel with $p=0.1$, and measure the qubit after this channel.\n",
    "**Note:** Noisy module in Paddle Quantum only supports density matrix operation mode."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2021-04-09T02:32:25.168455Z",
     "start_time": "2021-04-09T02:32:24.926709Z"
    },
    "scrolled": true
   },
   "outputs": [
    {
     "data": {
      "image/png": "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",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Quantum state after the bit flip quantum channel：\n",
      " [[0.8999999+0.j 0.       +0.j]\n",
      " [0.       +0.j 0.1      +0.j]]\n"
     ]
    }
   ],
   "source": [
    "# Noise level\n",
    "p = 0.1\n",
    "\n",
    "# Add the bit flip noisy channel\n",
    "cir.bit_flip(p, 0)\n",
    "\n",
    "# Execute the circuit\n",
    "# Note: Noisy module in Paddle Quantum only supports density matrix operation mode\n",
    "fin_state =  cir(init_state)\n",
    "\n",
    "# Measure in the computational basis\n",
    "fin_state.measure(shots = 1024, plot = True)\n",
    "print('Quantum state after the bit flip quantum channel：\\n', fin_state.data.numpy())"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "As we can see, the quantum state has been transformed to a mixed state $0.9 | 0 \\rangle \\langle 0 | + 0.1 | 1 \\rangle \\langle 1 |$ (with probability $p=0.1$ ) after the bit flip channel.\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Common quantum channels\n",
    "\n",
    "Paddle Quantum supports many other common noisy channels.\n",
    "\n",
    "- **Phase Flip Channel**\n",
    "\n",
    "  Similar to the bit-flip channel, the phase flip channel flips the phase of a qubit with probability $p$, \n",
    "  \n",
    "  $$\n",
    "  \\mathcal{E}_{PF}(\\rho) =  (1 - p) \\rho + p Z \\rho Z.\n",
    "  \\tag{6}\n",
    "  $$\n",
    "\n",
    "\n",
    "- **Bit-Phase Flip Channel**\n",
    "\n",
    "  $$\n",
    "  \\mathcal{E}_{BPF}(\\rho) = (1-p) \\rho + p Y \\rho Y.\n",
    "  \\tag{7}\n",
    "  $$\n",
    "\n",
    "\n",
    "- **Depolarizing Channel**\n",
    "\n",
    "  The quantum state will be in the maximally mixed state $I/2$ with probability $p$ or in the original state with probability $1-p$ after the single qubit depolarizing channel. The depolarizing channel can also be understood as applying Pauli noises symmetrically, \n",
    "  \n",
    "  $$\n",
    "  \\mathcal{E}_{D}(\\rho) = (1 - p) \\rho + \\frac{p}{3}\n",
    "  \\left( X \\rho X+ Y \\rho Y + Z \\rho Z \\right).\n",
    "  \\tag{8}\n",
    "  $$\n",
    "\n",
    "\n",
    "- **Pauli Channel**\n",
    "\n",
    "  The Pauli channel applies Pauli noises asymmetrically, \n",
    "  \n",
    "  $$\n",
    "  \\mathcal{E}_{Pauli}(\\rho) = (1 - p_x - p_y - p_z) \\rho + p_x X \\rho X + p_y Y \\rho Y + p_z Z \\rho Z.\n",
    "  \\tag{9}\n",
    "  $$\n",
    "\n",
    "\n",
    "- **Amplitude Damping Channel**\n",
    "\n",
    "  The amplitude damping channel can be used to model the process of **energy dissipation**, \n",
    "  \n",
    "  $$\n",
    "  \\mathcal{E}_{AD}(\\rho) = E_0 \\rho E_0^\\dagger + E_1 \\rho E_1^\\dagger,\n",
    "  \\tag{10}\n",
    "  $$\n",
    "  \n",
    "  where $\\gamma$ is the damping factor,\n",
    "  \n",
    "  $$\n",
    "  E_0 = \n",
    "  \\begin{bmatrix}\n",
    "   1 & 0 \\\\ 0 & \\sqrt{1 - \\gamma}\n",
    "  \\end{bmatrix},\n",
    "  E_1 = \n",
    "  \\begin{bmatrix}\n",
    "   0 & \\sqrt{\\gamma} \\\\ 0 & 0\n",
    "  \\end{bmatrix}.\n",
    "  \\tag{11}\n",
    "  $$ \n",
    "\n",
    "\n",
    "- **Phase Damping Channel**\n",
    "\n",
    "  The phase damping channel describes the loss of **quantum information** without loss of energy, \n",
    "  \n",
    "  $$\n",
    "  \\mathcal{E}_{PD}(\\rho) = E_0 \\rho E_0^\\dagger + E_1 \\rho E_1^\\dagger,\n",
    "  \\tag{12}\n",
    "  $$\n",
    "  \n",
    "  where $\\gamma$ is the damping factor，\n",
    "  \n",
    "  $$\n",
    "  E_0 = \n",
    "  \\begin{bmatrix}\n",
    "   1 & 0 \\\\ 0 & \\sqrt{1 - \\gamma}\n",
    "  \\end{bmatrix}, \n",
    "  E_1 = \n",
    "  \\begin{bmatrix}\n",
    "   0 & 0 \\\\ 0 & \\sqrt{\\gamma}\n",
    "  \\end{bmatrix}.\n",
    "  \\tag{13}\n",
    "  $$\n",
    "\n",
    "\n",
    "- **Generalized Amplitude Damping Channel**\n",
    "\n",
    "  The generalized amplitude damping channel describes energy exchange between the system and the environment at **finite temperatures**. It is a common noise in superconducting quantum computations [4]. Interested readers can find more information here [API document](https://qml.baidu.com/api/paddle_quantum.circuit.uansatz.html).\n",
    "\n",
    "\n",
    "**Note：** In Paddle Quantum, we can use these noisy channels through `Circuit.phase_flip()`, `Circuit.bit_phase_flip()`, `Circuit.depolarizing()`, `Circuit.pauli_channel()`, `Circuit.amplitude_damping()`, `Circuit.phase_damping()`, and `Circuit.generalized_amplitude_damping()`.\n",
    "\n",
    "**Note：** One usually choose the amplitude damping channel and the phase damping channel to model noises since they describe the physical process in real quantum systems (modeling $T_1$ and $T_2$ process)."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Customized Channel\n",
    "\n",
    "One can also use `Circuit.customized_channel()` in Paddle Quantum to add customized noisy channels. This is accomplished through user-defined Kraus operators. Here, we provide an example to reproduce the bit flip channel using customized_channel function:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2021-04-09T02:54:20.758898Z",
     "start_time": "2021-04-09T02:54:20.599327Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "quantum state after the customized channel:\n",
      " [[0.90000004+0.j 0.        +0.j]\n",
      " [0.        +0.j 0.1       +0.j]]\n",
      "\n",
      " quantum state after the bit flip channel：\n",
      " [[0.8999999+0.j 0.       +0.j]\n",
      " [0.       +0.j 0.1      +0.j]]\n",
      "\n",
      " are the two the same？ True\n"
     ]
    }
   ],
   "source": [
    "import paddle\n",
    "import numpy as np\n",
    "\n",
    "# Noise level\n",
    "p = 0.1\n",
    "\n",
    "# We use customized Kraus operator to represent the bit flip channel\n",
    "complex_dtype = paddle_quantum.get_dtype()\n",
    "a_0 = paddle.to_tensor(np.sqrt(1 - p) * np.array([[1, 0], [0, 1]], dtype=complex_dtype))\n",
    "a_1 = paddle.to_tensor(np.sqrt(p) * np.array([[0, 1], [1, 0]], dtype=complex_dtype))\n",
    "Kraus_ops = [a_0, a_1]\n",
    "\n",
    "# Initialize the circuit\n",
    "num_qubits = 1\n",
    "cir = Circuit(num_qubits)\n",
    "\n",
    "# Add customized channel, input is a list of Kraus operators\n",
    "cir.kraus_repr(Kraus_ops, 0)\n",
    "\n",
    "# Execute the circuit\n",
    "fin_state =  cir(init_state)\n",
    "\n",
    "# Compare the results\n",
    "cir_1 = Circuit(num_qubits)\n",
    "cir_1.bit_flip(p, 0)\n",
    "fin_state_1 = cir_1(init_state)\n",
    "print('quantum state after the customized channel:\\n', fin_state.data.numpy())\n",
    "print('\\n quantum state after the bit flip channel：\\n', fin_state_1.data.numpy())\n",
    "print('\\n are the two the same？', bool((fin_state.data - fin_state_1.data).abs().sum() < 1e-6))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Discussion: Simulating noisy entanglement resources with Paddle Quantum\n",
    "\n",
    "Many important quantum technologies require pre-shared entanglement resources, including quantum teleportation, state transformation, and distributed quantum computing. For instance, we want the allocated entanglement resources are in **maximally entangled states** under ideal circumstances. But in reality, noise always exists due to interactions between the system and the environment during preparation stage, transmission, and preservation. Here, we use the depolarizing channel to simulate how a white noise could affect Bell states: "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2021-04-09T02:58:30.352039Z",
     "start_time": "2021-04-09T02:58:30.311223Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Fidelity between the initial state and the Bell state 1\n",
      "after transmission (depolarizing channel), the fidelity between the entangled state and Bell state 0.81333\n",
      "after preservation (amplitude damping channel), the fidelity between the entangled state and Bell state 0.66752\n"
     ]
    }
   ],
   "source": [
    "import paddle\n",
    "from paddle import matmul, trace\n",
    "from paddle_quantum.ansatz import Circuit\n",
    "from paddle_quantum.state import bell_state\n",
    "\n",
    "# Noise level\n",
    "p_trans = 0.1\n",
    "p_store = 0.01\n",
    "\n",
    "# Initialize the circuit\n",
    "num_qubits = 2\n",
    "cir = Circuit(num_qubits)\n",
    "\n",
    "# The initial state is Bell state\n",
    "init_state = bell_state(2)\n",
    "\n",
    "# Apply the depolarizing channel to each qubit, modeling the noise introduced by transmission\n",
    "cir.depolarizing(p_trans, 0)\n",
    "cir.depolarizing(p_trans, 1)\n",
    "\n",
    "# Execute the circuit \n",
    "status_mid = cir(init_state)\n",
    "\n",
    "# Apply the amplitude damping channel to each qubit, modeling the noise introduced by storage\n",
    "cir.amplitude_damping(p_store, 0)\n",
    "cir.amplitude_damping(p_store, 1)\n",
    "\n",
    "# Execute the circuit\n",
    "status_fin = cir(status_mid)\n",
    "fidelity_mid = paddle.real(trace(matmul(init_state.data, status_mid.data)))\n",
    "fidelity_fin = paddle.real(trace(matmul(init_state.data, status_fin.data)))\n",
    "\n",
    "print(\"Fidelity between the initial state and the Bell state\", 1)\n",
    "print(\"after transmission (depolarizing channel), the fidelity between the entangled state and Bell state {:.5f}\".format(fidelity_mid.numpy()[0]))\n",
    "print(\"after preservation (amplitude damping channel), the fidelity between the entangled state and Bell state {:.5f}\".format(fidelity_fin.numpy()[0]))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Note：** Interested readers can check tutorials on the LOCCNet module of Paddle Quantum, where we discuss the concept of [entanglement distillation](../locc/EntanglementDistillation_LOCCNET_EN.ipynb)."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Application: Simulating noisy VQE with Paddle Quantum\n",
    "\n",
    "\n",
    "Variational Quantum Eigensolver (VQE) [5] is designed to find the ground state energy of a given molecular Hamiltonian using variational quantum circuits. Interested readers can find more details from the previous tutorial [VQE](../quantum_simulation/VQE_EN.ipynb).\n",
    "\n",
    "For illustration purposes, we use VQE to find the ground state energy for the following Hamiltonian: \n",
    "\n",
    "$$ \n",
    "H = 0.4 \\, Z \\otimes I + 0.4 \\, I \\otimes Z + 0.2 \\, X \\otimes X. \n",
    "\\tag{14}\n",
    "$$\n",
    "\n",
    "Then, we add the amplitude damping channel and compare the performance of the noisy circuit and the noiseless circuit on this task:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2021-04-09T03:06:13.534545Z",
     "start_time": "2021-04-09T03:06:13.523978Z"
    }
   },
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "import paddle\n",
    "from paddle_quantum.ansatz import Circuit\n",
    "from paddle_quantum.qinfo import pauli_str_to_matrix\n",
    "\n",
    "# Hyperparameters\n",
    "num_qubits = 2\n",
    "theta_size = 4\n",
    "ITR = 100\n",
    "LR = 0.4\n",
    "SEED = 999    \n",
    "p = 0.1\n",
    "\n",
    "# Construct Hamiltonian using Pauli string\n",
    "H_info = [[0.4, 'z0'], [0.4, 'z1'], [0.2, 'x0,x1']]\n",
    "\n",
    "# Convert the Pauli string to a matrix\n",
    "complex_dtype = paddle_quantum.get_dtype()\n",
    "H_matrix = pauli_str_to_matrix(H_info, num_qubits).numpy().astype(complex_dtype)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2021-04-09T03:06:36.986422Z",
     "start_time": "2021-04-09T03:06:32.444713Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "========== Training Noisy VQE ==========\n",
      "iter: 0   loss: -0.2139\n",
      "iter: 10   loss: -0.6206\n",
      "iter: 20   loss: -0.6481\n",
      "iter: 30   loss: -0.6588\n",
      "iter: 40   loss: -0.6599\n",
      "iter: 50   loss: -0.6607\n",
      "iter: 60   loss: -0.6618\n",
      "iter: 70   loss: -0.6621\n",
      "iter: 80   loss: -0.6621\n",
      "iter: 90   loss: -0.6621\n",
      "========== Training Noise Free VQE ==========\n",
      "iter: 0   loss: -0.0799\n",
      "iter: 10   loss: -0.7243\n",
      "iter: 20   loss: -0.8103\n",
      "iter: 30   loss: -0.8180\n",
      "iter: 40   loss: -0.8230\n",
      "iter: 50   loss: -0.8240\n",
      "iter: 60   loss: -0.8243\n",
      "iter: 70   loss: -0.8245\n",
      "iter: 80   loss: -0.8246\n",
      "iter: 90   loss: -0.8246\n",
      "\n",
      "Ground state energy from noisy circuit:  -0.66215336 Ha\n",
      "Ground state energy from noiseless circuit:  -0.82461333 Ha\n",
      "Actual ground state energy:  -0.82462114 Ha\n"
     ]
    }
   ],
   "source": [
    "class vqe_noisy(paddle.nn.Layer):\n",
    "    \n",
    "    def __init__(self):\n",
    "        super(vqe_noisy, self).__init__()\n",
    "\n",
    "        # Initialize circuit\n",
    "        self.cir = Circuit(num_qubits)\n",
    "        \n",
    "        # Add parameterized gates\n",
    "        self.cir.ry([0, 1])\n",
    "        \n",
    "        self.cir.cnot([0, 1])\n",
    "        \n",
    "        self.cir.ry([0, 1])\n",
    "        \n",
    "        # Add amplitude damping channel\n",
    "        self.cir.amplitude_damping(p, [0, 1])\n",
    "          \n",
    "    # Define loss function and forward function\n",
    "    def forward(self):\n",
    "          \n",
    "        # Execute the circuit\n",
    "        state = self.cir(init_state)\n",
    "        \n",
    "        # Expectation value of Hamiltonian \n",
    "        loss = loss_func(state)\n",
    "        \n",
    "        return loss, self.cir\n",
    "    \n",
    "# Construct a noiseless circuit\n",
    "class vqe_noise_free(paddle.nn.Layer):\n",
    "    \n",
    "    def __init__(self):\n",
    "        super(vqe_noise_free, self).__init__()\n",
    "        \n",
    "        self.cir = Circuit(num_qubits)\n",
    "        self.cir.ry([0, 1])\n",
    "        self.cir.cnot([0, 1])\n",
    "        self.cir.ry([0, 1])\n",
    "\n",
    "    def forward(self):\n",
    "        \n",
    "        state = self.cir(init_state)\n",
    "        loss = loss_func(state)\n",
    "        \n",
    "        return loss, self.cir\n",
    "    \n",
    "# Train noisy VQE circuit\n",
    "print('========== Training Noisy VQE ==========')\n",
    "loss_list = []\n",
    "parameter_list = []\n",
    "\n",
    "# Define the dimension of parameters\n",
    "vqe = vqe_noisy()\n",
    "\n",
    "# Generally, we use Adam optimizer to get a better convergence, you can change to SVG or RMS prop.\n",
    "opt = paddle.optimizer.Adam(learning_rate = LR, parameters = vqe.parameters()) \n",
    "\n",
    "# Define initial state\n",
    "init_state = paddle_quantum.state.zero_state(num_qubits)\n",
    "\n",
    "# Define loss function\n",
    "loss_func = paddle_quantum.loss.ExpecVal(paddle_quantum.Hamiltonian(H_info))\n",
    "\n",
    "# Optimization iteration\n",
    "for itr in range(ITR):\n",
    "\n",
    "    # Forward, to calculate loss function\n",
    "    loss, cir = vqe()\n",
    "\n",
    "    # Backpropagate to minimize the loss function\n",
    "    loss.backward()\n",
    "    opt.minimize(loss)\n",
    "    opt.clear_grad()\n",
    "\n",
    "    # Record the learning curve\n",
    "    loss_list.append(loss.numpy()[0])\n",
    "    parameter_list.append(vqe.parameters()[0].numpy())\n",
    "    if itr % 10 == 0:\n",
    "        print('iter:', itr, '  loss: %.4f' % loss.numpy())\n",
    "        \n",
    "# Train the noiseless VQE in the same way\n",
    "print('========== Training Noise Free VQE ==========')\n",
    "loss_list_no_noise = []\n",
    "parameter_list_no_noise = []\n",
    "\n",
    "vqe_no_noise = vqe_noise_free()\n",
    "opt_no_noise = paddle.optimizer.Adam(learning_rate = LR, parameters = vqe_no_noise.parameters())    \n",
    "\n",
    "for itr in range(ITR):\n",
    "\n",
    "    loss, cir = vqe_no_noise()\n",
    "\n",
    "    loss.backward()\n",
    "    opt_no_noise.minimize(loss)\n",
    "    opt_no_noise.clear_grad()\n",
    "\n",
    "    loss_list_no_noise.append(loss.numpy()[0])\n",
    "    parameter_list_no_noise.append(vqe_no_noise.parameters()[0].numpy())\n",
    "    if itr % 10 == 0:\n",
    "        print('iter:', itr, '  loss: %.4f' % loss.numpy())\n",
    "\n",
    "\n",
    "print('\\nGround state energy from noisy circuit: ', loss_list[-1], \"Ha\")\n",
    "print('Ground state energy from noiseless circuit: ', loss_list_no_noise[-1], \"Ha\")\n",
    "print('Actual ground state energy: ', np.linalg.eigh(H_matrix)[0][0], \"Ha\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "As we can see, noisy VQE behaves much worse than the noiseless version as expected and couldn't satisfy chemical accuracy $\\varepsilon = 0.0016$ Ha."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Conclusion\n",
    "\n",
    "Noise is an unavoidable feature of quantum devices in the NISQ era. Therefore, designing robust quantum algorithms under the presence of noise and further developing error mitigation schemes are two important research directions. With the noise module in Paddle Quantum, we hope to provide a platform simulating real physical systems and help developing near-term quantum computation applications. Standing together with the research community, the noise module will help us explore what we can achieve with noisy devices, design more robust quantum algorithms, and eventually leads to trustworthy quantum solutions in areas including AI and quantum chemistry.\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "---\n",
    "\n",
    "## References\n",
    "\n",
    "[1] Iverson, J. K., & Preskill, J. Coherence in logical quantum channels. [New Journal of Physics, 22(7), 073066 (2020).](https://iopscience.iop.org/article/10.1088/1367-2630/ab8e5c)\n",
    "\n",
    "[2] Nielsen, M. A. & Chuang, I. L. Quantum computation and quantum information. Cambridge university press (2010).\n",
    "\n",
    "[3] Preskill, J. Quantum Information Lecture Notes. Chapter 3 (2018).\n",
    "\n",
    "[4] Chirolli, L., & Burkard, G. Decoherence in solid-state qubits. [Advances in Physics, 57(3), 225-285 (2008).](https://www.tandfonline.com/doi/abs/10.1080/00018730802218067)\n",
    "\n",
    "[5] Peruzzo, A. et al. A variational eigenvalue solver on a photonic quantum processor. [Nat. Commun. 5, 4213 (2014).](https://www.nature.com/articles/ncomms5213)"
   ]
  }
 ],
 "metadata": {
  "interpreter": {
   "hash": "4261e4eef114648d37e4a637967bd8d2966507f48b194e5e336ba3366b740269"
  },
  "kernelspec": {
   "display_name": "Python 3.8.13 ('pq-ns-icode')",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.13"
  },
  "toc": {
   "base_numbering": 1,
   "nav_menu": {},
   "number_sections": true,
   "sideBar": true,
   "skip_h1_title": false,
   "title_cell": "Table of Contents",
   "title_sidebar": "Contents",
   "toc_cell": false,
   "toc_position": {},
   "toc_section_display": true,
   "toc_window_display": false
  },
  "varInspector": {
   "cols": {
    "lenName": 16,
    "lenType": 16,
    "lenVar": 40
   },
   "kernels_config": {
    "python": {
     "delete_cmd_postfix": "",
     "delete_cmd_prefix": "del ",
     "library": "var_list.py",
     "varRefreshCmd": "print(var_dic_list())"
    },
    "r": {
     "delete_cmd_postfix": ") ",
     "delete_cmd_prefix": "rm(",
     "library": "var_list.r",
     "varRefreshCmd": "cat(var_dic_list()) "
    }
   },
   "types_to_exclude": [
    "module",
    "function",
    "builtin_function_or_method",
    "instance",
    "_Feature"
   ],
   "window_display": false
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
